package cn.harry.cabinet.server.routes

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Base64
import android.util.Log
import cn.harry.cabinet.arcface.faceserver.FaceServer
import cn.harry.cabinet.constants.StorageConstants
import cn.harry.cabinet.server.dto.common.ApiResponse
import cn.harry.cabinet.server.dto.feature.BatchFeatureUploadRequest
import cn.harry.cabinet.server.dto.feature.BatchFeatureUploadResponse
import cn.harry.cabinet.server.dto.feature.FeatureListItem
import cn.harry.cabinet.server.dto.feature.FeatureListResponse
import cn.harry.cabinet.server.dto.feature.FeatureUploadRequest
import cn.harry.cabinet.server.dto.feature.FeatureUploadResponse
import com.arcsoft.face.FaceEngine
import com.arcsoft.face.FaceInfo
import com.arcsoft.face.enums.DetectFaceOrientPriority
import com.arcsoft.face.enums.DetectMode
import io.ktor.http.HttpStatusCode
import io.ktor.http.content.PartData
import io.ktor.http.content.streamProvider
import io.ktor.server.application.call
import io.ktor.server.request.receive
import io.ktor.server.request.receiveMultipart
import io.ktor.server.response.respond
import io.ktor.server.routing.Route
import io.ktor.server.routing.delete
import io.ktor.server.routing.get
import io.ktor.server.routing.post
import io.ktor.server.routing.route
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.serialization.InternalSerializationApi
import java.io.File
import java.io.FileOutputStream

/**
 * 特征库API路由
 * 提供特征码上传、查询、删除等功能
 */
@OptIn(InternalSerializationApi::class)
fun Route.featureRoutes(context: Context) {
    
    // 使用统一的存储路径常量
    val featureDir = StorageConstants.getFeatureDir(context)
    val imageDir = StorageConstants.getImageDir(context)
    
    // 确保目录存在
    StorageConstants.ensureDirectoriesExist(context)
    
    val TAG = "FeatureRoutes"
    
    route("/api/features") {
        
        // 获取特征列表
        get {
            try {
                withContext(Dispatchers.IO) {
                    val featureDirFile = File(featureDir)
                    val features = mutableListOf<FeatureListItem>()
                    
                    featureDirFile.listFiles()?.forEach { file ->
                        if (file.isFile) {
                            val name = file.nameWithoutExtension
                            val time = file.lastModified()
                            val imgFile = File(imageDir, "$name.jpg")
                            val hasImage = imgFile.exists()
                            val imagePath = if (hasImage) imgFile.absolutePath else null
                            
                            features.add(FeatureListItem(name, time, hasImage, imagePath))
                        }
                    }
                    
                    // 按时间倒序排序
                    features.sortByDescending { it.time }
                    
                    val response = FeatureListResponse(
                        features = features,
                        totalCount = features.size
                    )
                    
                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(response, "获取特征列表成功")
                    )
                }
            } catch (e: Exception) {
                call.respondError("获取特征列表失败", e)
            }
        }
        
        // 上传单个特征（Base64格式）
        post("/upload") {
            try {
                println("收到上传请求")
                val request = call.receive<FeatureUploadRequest>()
                println("解析成功: name=${request.name}, imageBase64长度=${request.imageBase64.length}")
                
                // 验证请求
                if (!request.isValid()) {
                    val errors = request.getValidationErrors()
                    call.respondBadRequest(errors.joinToString(", "))
                    return@post
                }
                
                withContext(Dispatchers.IO) {
                    val result = saveFeatureFromBase64(
                        context,
                        request.name,
                        request.imageBase64,
                        imageDir,
                        featureDir
                    )
                    
                    if (result.success) {
                        call.respond(
                            HttpStatusCode.Created,
                            ApiResponse.success(result, "上传特征成功")
                        )
                    } else {
                        call.respond(
                            HttpStatusCode.BadRequest,
                            ApiResponse.errorResponse(400, result.message)
                        )
                    }
                }
            } catch (e: Exception) {
                call.respondError("上传特征失败", e)
            }
        }
        
        // 批量上传特征
        post("/upload/batch") {
            try {
                val request = call.receive<BatchFeatureUploadRequest>()
                
                if (!request.isValid()) {
                    call.respondBadRequest("批量上传请求无效")
                    return@post
                }
                
                withContext(Dispatchers.IO) {
                    val results = mutableListOf<FeatureUploadResponse>()
                    var successCount = 0
                    var failCount = 0
                    
                    request.features.forEach { feature ->
                        val result = saveFeatureFromBase64(
                            context,
                            feature.name,
                            feature.imageBase64,
                            imageDir,
                            featureDir
                        )
                        
                        results.add(result)
                        if (result.success) {
                            successCount++
                        } else {
                            failCount++
                        }
                    }
                    
                    val batchResponse = BatchFeatureUploadResponse(
                        totalCount = request.features.size,
                        successCount = successCount,
                        failCount = failCount,
                        results = results
                    )
                    
                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(batchResponse, "批量上传完成")
                    )
                }
            } catch (e: Exception) {
                call.respondError("批量上传失败", e)
            }
        }
        
        // 上传特征（multipart/form-data格式）
        post("/upload/multipart") {
            try {
                withContext(Dispatchers.IO) {
                    val multipart = call.receiveMultipart()
                    var name: String? = null
                    var imageFile: File? = null
                    
                    var part = multipart.readPart()
                    while (part != null) {
                        when (part) {
                            is PartData.FormItem -> {
                                when (part.name) {
                                    "name" -> name = part.value
                                }
                            }
                            is PartData.FileItem -> {
                                if (part.name == "image") {
                                    val fileName = part.originalFileName ?: "temp_${System.currentTimeMillis()}.jpg"
                                    val tempFile = File.createTempFile("upload_", fileName)
                                    part.streamProvider().use { input ->
                                        FileOutputStream(tempFile).use { output ->
                                            input.copyTo(output)
                                        }
                                    }
                                    imageFile = tempFile
                                }
                            }
                            else -> {}
                        }
                        part.dispose()
                        part = multipart.readPart()
                    }
                    
                    // 验证必需参数
                    if (name.isNullOrBlank() || imageFile == null) {
                        call.respondBadRequest("缺少必需参数：name 和 image")
                        imageFile?.delete()
                        return@withContext
                    }
                    
                    // 读取图片文件并进行人脸检测和特征提取
                    val bitmap = BitmapFactory.decodeFile(imageFile!!.absolutePath)
                    imageFile!!.delete()
                    
                    if (bitmap == null) {
                        call.respond(
                            HttpStatusCode.BadRequest,
                            ApiResponse.errorResponse(400, "图片解码失败")
                        )
                        return@withContext
                    }
                    
                    // 使用统一的处理逻辑
                    val result = processImageAndExtractFeature(
                        context,
                        name!!,
                        bitmap,
                        imageDir,
                        featureDir
                    )
                    
                    if (result.success) {
                        call.respond(
                            HttpStatusCode.Created,
                            ApiResponse.success(result, "上传特征成功")
                        )
                    } else {
                        call.respond(
                            HttpStatusCode.BadRequest,
                            ApiResponse.errorResponse(400, result.message)
                        )
                    }
                }
            } catch (e: Exception) {
                call.respondError("上传特征失败", e)
            }
        }
        
        // 删除特征
        delete("/{name}") {
            try {
                val name = call.parameters["name"]
                if (name.isNullOrBlank()) {
                    call.respondBadRequest("特征名称不能为空")
                    return@delete
                }
                
                withContext(Dispatchers.IO) {
                    var deleted = false
                    
                    // 删除特征文件
                    val featureFile = File(featureDir, name)
                    if (featureFile.exists()) {
                        featureFile.delete()
                        deleted = true
                    }
                    
                    // 删除图片文件
                    val imageFile = File(imageDir, "$name.jpg")
                    if (imageFile.exists()) {
                        imageFile.delete()
                        deleted = true
                    }
                    
                    if (deleted) {
                        call.respond(
                            HttpStatusCode.OK,
                            ApiResponse.success(message = "删除特征成功")
                        )
                    } else {
                        call.respondNotFound("特征不存在")
                    }
                }
            } catch (e: Exception) {
                call.respondError("删除特征失败", e)
            }
        }
        
        // 批量删除特征
        post("/delete/batch") {
            try {
                @kotlinx.serialization.Serializable
                data class BatchDeleteRequest(val names: List<String>)
                
                val request = call.receive<BatchDeleteRequest>()
                
                if (request.names.isEmpty()) {
                    call.respondBadRequest("删除列表不能为空")
                    return@post
                }
                
                withContext(Dispatchers.IO) {
                    var successCount = 0
                    var failCount = 0
                    
                    request.names.forEach { name ->
                        var deleted = false
                        
                        // 删除特征文件
                        val featureFile = File(featureDir, name)
                        if (featureFile.exists()) {
                            featureFile.delete()
                            deleted = true
                        }
                        
                        // 删除图片文件
                        val imageFile = File(imageDir, "$name.jpg")
                        if (imageFile.exists()) {
                            imageFile.delete()
                            deleted = true
                        }
                        
                        if (deleted) {
                            successCount++
                        } else {
                            failCount++
                        }
                    }
                    
                    @kotlinx.serialization.Serializable
                    data class BatchDeleteResponse(
                        val totalCount: Int,
                        val successCount: Int,
                        val failCount: Int
                    )
                    
                    val response = BatchDeleteResponse(
                        totalCount = request.names.size,
                        successCount = successCount,
                        failCount = failCount
                    )
                    
                    call.respond(
                        HttpStatusCode.OK,
                        ApiResponse.success(response, "批量删除完成")
                    )
                }
            } catch (e: Exception) {
                call.respondError("批量删除失败", e)
            }
        }
    }
}

/**
 * 从 Base64 保存特征（包含人脸检测和特征提取）
 */
@OptIn(InternalSerializationApi::class)
private fun saveFeatureFromBase64(
    context: Context,
    name: String,
    imageBase64: String,
    imageDir: String,
    featureDir: String
): FeatureUploadResponse {
    return try {
        // 移除Base64前缀（如果存在）
        val base64Data = if (imageBase64.contains(",")) {
            imageBase64.substringAfter(",")
        } else {
            imageBase64
        }
        
        // 解码Base64图片
        val imageBytes = Base64.decode(base64Data, Base64.DEFAULT)
        val bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
        
        if (bitmap == null) {
            return FeatureUploadResponse(
                name = name,
                success = false,
                message = "图片解码失败"
            )
        }
        
        // 使用通用方法处理
        val result = processImageAndExtractFeature(context, name, bitmap, imageDir, featureDir)
        bitmap.recycle()
        result
    } catch (e: Exception) {
        Log.e("FeatureRoutes", "保存特征失败: $name", e)
        FeatureUploadResponse(
            name = name,
            success = false,
            message = "保存失败: ${e.message}"
        )
    }
}

/**
 * 从 Bitmap 处理图片并提取特征（通用方法）
 */
@OptIn(InternalSerializationApi::class)
private fun processImageAndExtractFeature(
    context: Context,
    name: String,
    bitmap: Bitmap,
    imageDir: String,
    featureDir: String
): FeatureUploadResponse {
    var faceEngine: FaceEngine? = null
    return try {
        // 保存图片
        val imageFile = File(imageDir, "$name.jpg")
        FileOutputStream(imageFile).use { out ->
            bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out)
        }
        
        // 进行人脸检测和特征提取
        Log.i("FeatureRoutes", "开始检测人脸: $name")
        val featureFile = File(featureDir, name)
        
        // 转换为 NV21 格式
        val width = bitmap.width
        val height = bitmap.height
        val nv21 = bitmapToNv21(bitmap, width, height)
        
        // 初始化 FaceEngine
        faceEngine = FaceEngine()
        val initCode = faceEngine.init(
            context,
            DetectMode.ASF_DETECT_MODE_IMAGE,
            DetectFaceOrientPriority.ASF_OP_0_ONLY,
            16,
            10,
            FaceEngine.ASF_FACE_DETECT or FaceEngine.ASF_FACE_RECOGNITION
        )
        
        if (initCode != 0) {
            bitmap.recycle()
            return FeatureUploadResponse(
                name = name,
                success = false,
                message = "初始化人脸引擎失败，错误码: $initCode"
            )
        }
        
        // 检测人脸
        val faceInfoList = mutableListOf<FaceInfo>()
        val detectCode = faceEngine.detectFaces(
            nv21,
            width,
            height,
            FaceEngine.CP_PAF_NV21,
            faceInfoList
        )
        
        if (detectCode != 0 || faceInfoList.isEmpty()) {
            bitmap.recycle()
            return FeatureUploadResponse(
                name = name,
                success = false,
                message = "未检测到人脸，错误码: $detectCode"
            )
        }
        
        Log.i("FeatureRoutes", "检测到 ${faceInfoList.size} 个人脸")
        
        // 提取人脸特征
        val faceFeature = com.arcsoft.face.FaceFeature()
        val extractCode = faceEngine.extractFaceFeature(
            nv21,
            width,
            height,
            FaceEngine.CP_PAF_NV21,
            faceInfoList[0],
            faceFeature
        )
        
        if (extractCode != 0) {
            bitmap.recycle()
            return FeatureUploadResponse(
                name = name,
                success = false,
                message = "提取人脸特征失败，错误码: $extractCode"
            )
        }
        
        // 保存特征数据
        FileOutputStream(featureFile).use { fos ->
            fos.write(faceFeature.featureData)
        }
        
        Log.i("FeatureRoutes", "特征提取成功: $name")
        Log.i("FeatureRoutes", "特征文件路径: ${featureFile.absolutePath}")
        Log.i("FeatureRoutes", "特征数据大小: ${faceFeature.featureData.size} bytes")
        Log.i("FeatureRoutes", "特征文件大小: ${featureFile.length()} bytes")
        
        val featurePath = featureFile.absolutePath
        
        bitmap.recycle()
        
        // 重新加载 FaceServer 特征列表
        Log.i("FeatureRoutes", "开始重新加载特征列表...")
        FaceServer.getInstance().reloadFaceList(context)
        Log.i("FeatureRoutes", "特征列表重新加载完成")
        
        FeatureUploadResponse(
            name = name,
            success = true,
            message = "注册成功",
            imagePath = imageFile.absolutePath,
            featurePath = featurePath
        )
    } catch (e: Exception) {
        Log.e("FeatureRoutes", "保存特征失败: $name", e)
        FeatureUploadResponse(
            name = name,
            success = false,
            message = "保存失败: ${e.message}"
        )
    } finally {
        faceEngine?.unInit()
    }
}

/**
 * 将 Bitmap 转换为 NV21 格式
 */
private fun bitmapToNv21(bitmap: Bitmap, width: Int, height: Int): ByteArray {
    val argb = IntArray(width * height)
    bitmap.getPixels(argb, 0, width, 0, 0, width, height)
    
    val yuv = ByteArray(width * height * 3 / 2)
    encodeYUV420SP(yuv, argb, width, height)
    
    return yuv
}

/**
 * RGB 转 YUV420SP (NV21)
 */
private fun encodeYUV420SP(yuv420sp: ByteArray, argb: IntArray, width: Int, height: Int) {
    val frameSize = width * height
    var yIndex = 0
    var uvIndex = frameSize
    
    var R: Int
    var G: Int
    var B: Int
    var Y: Int
    var U: Int
    var V: Int
    
    var index = 0
    for (j in 0 until height) {
        for (i in 0 until width) {
            R = (argb[index] and 0xff0000) shr 16
            G = (argb[index] and 0xff00) shr 8
            B = argb[index] and 0xff
            
            Y = ((66 * R + 129 * G + 25 * B + 128) shr 8) + 16
            U = ((-38 * R - 74 * G + 112 * B + 128) shr 8) + 128
            V = ((112 * R - 94 * G - 18 * B + 128) shr 8) + 128
            
            yuv420sp[yIndex++] = (if (Y < 0) 0 else if (Y > 255) 255 else Y).toByte()
            
            if (j % 2 == 0 && index % 2 == 0) {
                yuv420sp[uvIndex++] = (if (V < 0) 0 else if (V > 255) 255 else V).toByte()
                yuv420sp[uvIndex++] = (if (U < 0) 0 else if (U > 255) 255 else U).toByte()
            }
            
            index++
        }
    }
}

/**
 * 响应错误请求
 */
@OptIn(InternalSerializationApi::class)
private suspend fun io.ktor.server.application.ApplicationCall.respondBadRequest(message: String) {
    respond(
        HttpStatusCode.BadRequest,
        ApiResponse.errorResponse(400, message)
    )
}

/**
 * 响应未找到错误
 */
@OptIn(InternalSerializationApi::class)
private suspend fun io.ktor.server.application.ApplicationCall.respondNotFound(message: String) {
    respond(
        HttpStatusCode.NotFound,
        ApiResponse.errorResponse(404, message)
    )
}

/**
 * 响应服务器错误
 */
@OptIn(InternalSerializationApi::class)
private suspend fun io.ktor.server.application.ApplicationCall.respondError(message: String, exception: Exception) {
    println("$message: ${exception.javaClass.simpleName} - ${exception.message}")
    exception.printStackTrace()
    
    respond(
        HttpStatusCode.InternalServerError,
        ApiResponse.errorResponse(500, "$message: ${exception.message}")
    )
}
